function bindActionCreator(actionCreator, dispatch) {
  // 包装一层dispatch，返回高阶函数，因为原来的actionCreator是可以传递参数的函数，包装后不能破坏原结构
  return (...args) => dispatch(actionCreator(...args))
}

/**
  *将值为动作创建者的对象转换为具有该对象的对象
  *相同的键，但每个函数都包含在`dispatch`调用中，所以它们
  *可以直接调用。 这只是一种方便的方法，你可以打电话
  *`store.dispatch（MyActionCreators.doSomething（））`你自己就好了。
  *
  *为方便起见，您还可以将单个函数作为第一个参数传递，
  *并获得一个功能作为回报。
  *
  * @param {Function | Object} actionCreators值为action的对象
  *创作者功能。 获得它的一个方便方法是使用ES6`import *作为`
  * 句法。 您也可以传递一个函数。
  *
  * @param {Function} dispatch Redux上提供的`dispatch`功能
  *商店。
  *
  * @returns {Function | Object}模仿原始对象的对象，但是带有
  *每个动作创建者都包含在`dispatch`调用中。 如果你通过了
  *函数为`actionCreators`，返回值也将是单个功能。
  */
export default function bindActionCreators(actionCreators, dispatch) {
  if (typeof actionCreators === 'function') {
    return bindActionCreator(actionCreators, dispatch)
  }

  if (typeof actionCreators !== 'object' || actionCreators === null) {
    throw new Error(
      `bindActionCreators expected an object or a function, instead received ${actionCreators === null ? 'null' : typeof actionCreators}. ` +
      `Did you write "import ActionCreators from" instead of "import * as ActionCreators from"?`
    )
  }

  //如果actionCreators是一个redux函数集合就讲dsipath进行遍历绑定 
  const keys = Object.keys(actionCreators)
  const boundActionCreators = {}
  // 遍历 actionCreators 对象上的函数集合，每个都进行 dispatch 绑定。
  for (let i = 0; i < keys.length; i++) {
    const key = keys[i]
    const actionCreator = actionCreators[key]
    if (typeof actionCreator === 'function') {
      // 包装函数：在原函数上增加dispatch包装。
      // 我们直接把经过dispatch包装过函数传递给子组件，而不是让子组件拿到传递过去dispatch
        // 再去执行，这样子组件只通过传递过去的函数调用即可，完全不知道有redux的存在
      boundActionCreators[key] = bindActionCreator(actionCreator, dispatch)
    }
  }
  return boundActionCreators
}
